import { formatTime } from '@gnlab/utils'
import { emojiMap, default as Emoji } from '@/desktop/components/Emoji'

/**
 * 格式化聊天消息
 */
export function formatTextContent(
  content: string | undefined,
  extraFormatter?: (nodes: (string | JSX.Element)[]) => (string | JSX.Element)[],
) {
  let parts = transformEmoji(content ?? '')
  if (extraFormatter) parts = extraFormatter(parts)
  return parts.map((v, i) => (typeof v === 'string' ? <span key={i}>{v}</span> : v))
}

function transformEmoji(content: string) {
  // 下面 split 的内容可以用这一句快速完成：content.split(/(?=\[)|(?<=\])/)，但因为 Safari 不支持，改用了一个较复杂的方式。
  const parts = content
    .replace(/\t/g, ' ')
    .replace(/\[/g, '\t[')
    .replace(/\]/g, ']\t')
    .split('\t')
    .map((txt, i) => (emojiMap.has(txt) ? <Emoji key={i} code={txt} /> : txt))
  return parts
}

/**
 * 返回聊天所需格式的时间
 */
export function formatChatTime(d: Date | string | number) {
  return formatTime(d, { short: true, simple: false })
}

// 设置光标位置
export const setRange = (node: Node, offset: number) => {
  const selection = getSelection()
  if (!selection) return

  const range = document.createRange()
  range.selectNodeContents(node)
  try {
    range.setStart(node, offset)
  } catch (e) {
    range.setStart(node, node.childNodes.length)
  }
  // 使光标开始和光标结束重叠
  range.collapse(true)
  // 清除选定对象的所有光标对象
  selection.removeAllRanges()
  // 插入新的光标对象
  selection.addRange(range)
}

/**
 * 计算图片/视频的显示宽度和高度
 */
export function calcuteMediaStyle(params: {
  // loaded: 资源是否正在加载。
  // 明确指定为 true 时，若 height 无值，会把 maxHeight 临时作为 height，
  // 使得加载完成后资源的显示高度只会变低、不会变高，以保证聊天滚动条保持在底部。
  // （元素从高变低，已经处于底部的滚动条不会受影响，从低到高则会移动）
  loading?: boolean
  width?: number
  height?: number
  maxWidth: number
  maxHeight: number
}) {
  const { loading = false, maxWidth, maxHeight } = params
  let { width = 0, height = 0 } = params

  if (loading && height === 0) {
    height = maxHeight
    width = 0
  }

  // 为符合显示要求，宽度和高度各要缩小到原本的几分之一。保底为 1/1，也就是尺寸小于 max 尺寸时不再缩小。
  const widthScale = Math.max(width / maxWidth, 1)
  const heightScale = Math.max(height / maxHeight, 1)
  // 选定要缩得更多的那方
  const finalScale = Math.max(widthScale, heightScale)

  return {
    width: width ? `${Math.round(width / finalScale)}px` : 'auto',
    height: height ? `${Math.round(height / finalScale)}px` : 'auto',
    maxWidth: `${maxWidth}px`,
    maxHeight: `${maxHeight}px`,
  }
}

/**
 * 控制一段长文字的展开、收起
 * text: 要显示的文字
 * limit: 达到多少字时启用“收起”功能
 */
export function useFold(text: string, limit = 50) {
  const enableFold = text.length > limit
  const [fold, setFold] = useState(enableFold)
  const showingText = fold ? text.slice(0, limit) : text
  return {
    showingText,
    fold: enableFold ? fold : null,
    switchFold: () => setFold(!fold),
  }
}
